package com.tfjybj.itoo.teach.provider.service.impl;
/*
  @auther 井朝
  @DESCRIPTION 选课
  @since 1.0.8 2018/11/15
*/

import com.dmsdbj.itoo.tool.base.service.impl.BaseServicePlusImpl;
import com.dmsdbj.itoo.tool.constantutil.YearSemester;
import com.tfjybj.itoo.teach.entity.CourseEntity;
import com.tfjybj.itoo.teach.entity.SchoolCalendarEntity;
import com.tfjybj.itoo.teach.entity.StudentEntity;
import com.tfjybj.itoo.teach.model.AddCourseInfo;
import com.tfjybj.itoo.teach.model.AddCourseModel;
import com.tfjybj.itoo.teach.model.ChooseCourseModel;
import com.tfjybj.itoo.teach.model.CourseScheduleModel;
import com.tfjybj.itoo.teach.provider.dao.ChooseCourseDao;
import com.tfjybj.itoo.teach.provider.service.ChooseCourseService;
import com.tfjybj.itoo.teach.provider.service.CourseScheduleService;
import com.tfjybj.itoo.teach.provider.service.StudentService;
import com.tfjybj.itoo.teach.provider.service.StudentTeachClassService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service("chooseCourseService")
public class ChooseCourseServiceImpl extends BaseServicePlusImpl<ChooseCourseDao, ChooseCourseModel> implements ChooseCourseService {


    private final DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式

    //todo:
    @Resource
    private ChooseCourseDao chooseCourseDao;
    @Autowired
    private StudentService studentService;
    @Autowired
    private StudentTeachClassService studentTeachClassService;
    @Autowired
    private CourseScheduleService courseScheduleService;


    /**
     * 查询未选课  井朝 2018年11月19日14:49:38
     * 非本学院/本专业
     *
     * @param studentId 学生id
     * @return 未选课信息
     * @throws IOException 异常信息
     */
    @Override
    public List<ChooseCourseModel> queryUnSelectedCourse(String studentId) throws IOException, ParseException {

        List<ChooseCourseModel> chooseCourseModelList = new ArrayList<>();
        List<ChooseCourseModel> queryUnSelectCourseList;
        //判断是否在选课时间内
        if (idDeadLine()) {
            return null;
        }
        //根据学生id查询专业学院
        StudentEntity studentModel = studentService.getById(studentId);
        //查询学年学期
        String semesterId = YearSemester.getYearSemesterCode(1, 1).get(0);

        if (studentModel != null) {
            //根据班级和学年学期，联查课程表和课程池查询基于学院的公共选修课
            String classId = studentModel.getClassesId();
            List<ChooseCourseModel> pubAllChooseCourse = chooseCourseDao.getPublicFromDB(semesterId, classId);
            //根据专业和学年学期，联查课程表和培养计划表查询基于专业的专业选修课
            String professionId = studentModel.getProfessionId();
            List<ChooseCourseModel> majAllChooseCourse = chooseCourseDao.getMajorFromDB(professionId, semesterId);
            //两个List相加
            chooseCourseModelList.addAll(majAllChooseCourse);
            chooseCourseModelList.addAll(pubAllChooseCourse);
        }

        //移除已选课的List ，返回
        if (CollectionUtils.isEmpty(chooseCourseModelList)) {
            queryUnSelectCourseList = chooseCourseModelList;
        } else {
            //查询已选课
            queryUnSelectCourseList = selectNoConflictsCourse(studentId, chooseCourseModelList);
        }
        return queryUnSelectCourseList;
    }

    /**
     * 额外添加-筛出已选课程 井朝 2018年12月07日14:52:33
     *
     * @param studentId             学生id
     * @param chooseCourseModelList 除本学院外的公选课信息
     * @return 与已选课程时间不冲突的课程信息
     */
    private List<ChooseCourseModel> selectNoConflictsCourse(String studentId, List<ChooseCourseModel> chooseCourseModelList) {

        //查询学生已选课
        List<ChooseCourseModel> selectedCourseList = selectStudentSelectedCourse(studentId);
        //如果学生还未选过课,则不需要筛选
        if (selectedCourseList == null || selectedCourseList.size() == 0) {
            return chooseCourseModelList;
        }
        //循环可选课程，把已选课程移除
//        Optional<ChooseCourseModel> chooseCourseModel1 = Optional.empty();
//        for (ChooseCourseModel chooseCourseModel : selectedCourseList) {
//            if (!StringUtils.isEmpty(chooseCourseModel.getCourseId()) && (chooseCourseModel.getCourseId() != null)) {
//                chooseCourseModel1 = chooseCourseModelList.stream().filter(courseModel ->
//                        courseModel.getCourseId().equals(chooseCourseModel.getCourseId())).findAny();
//            }

            chooseCourseModelList.removeAll(selectedCourseList);
        return chooseCourseModelList;
    }

    /**
     * 查询学生已选课信息 井朝 2018年12月07日14:53:54
     *
     * @param studentId 学生id
     * @return 学生已选课信息
     * throws IOException 异常信息
     */
    @Override
    public List<ChooseCourseModel> selectStudentSelectedCourse(String studentId) {
        List<ChooseCourseModel> studentSelectedCourse = new ArrayList<>();
        //获取当前学年学期id
        String semesterCode = YearSemester.getYearSemesterCode(1, 1).get(0);
        //通过学生id查询上课班id
        List<String> selectdeTeachClass = studentTeachClassService.findTeachClassIdsByStudentId(studentId);
        //通过上课班id和学年学期在课程表中返回课程id的集合
        if (selectdeTeachClass != null && selectdeTeachClass.size() != 0) {
            List<String> ScheduleCourseIds = courseScheduleService.queryCourseIdsByTeachClassIds(selectdeTeachClass);
            //筛选只是公选课和专选课的信息
            if (ScheduleCourseIds != null && ScheduleCourseIds.size() != 0) {
                List<String> CourseIds = chooseCourseDao.queryAllCourseByIds(ScheduleCourseIds);
                if (CourseIds == null || CourseIds.size() == 0) {
                    return studentSelectedCourse;
                }
                List<CourseScheduleModel> courseAlllist = courseScheduleService.queryCourseScheduleByIds(CourseIds);
                List<CourseEntity> courseInfo = chooseCourseDao.queryAllCourseType(CourseIds);
                Map<String, List<CourseEntity>> courseInfoMap = courseInfo.stream().collect(Collectors.groupingBy(CourseEntity::getId));
                for (CourseScheduleModel courseScheduleModel :courseAlllist) {

                    List<CourseEntity> courseEntity = courseInfoMap.get(courseScheduleModel.getCourseId());
                    ChooseCourseModel chooseCourseModel = new ChooseCourseModel();
                    chooseCourseModel.setCourseId(courseScheduleModel.getCourseId());
                    chooseCourseModel.setTeacherId(courseScheduleModel.getTeacherId());
                    chooseCourseModel.setTeacherName(courseScheduleModel.getTeacherName());
                    chooseCourseModel.setCourseName(courseScheduleModel.getCourseName());
                    chooseCourseModel.setRoomId(courseScheduleModel.getRoomId());
                    chooseCourseModel.setTeachClassId(courseScheduleModel.getTeachClassId());
                    chooseCourseModel.setCellTimeId(courseScheduleModel.getCellTimeId());
                    chooseCourseModel.setClassPoint(courseEntity.get(0).getClassPoint());
                    chooseCourseModel.setWeekId(courseScheduleModel.getWeekId());
                    chooseCourseModel.setCourseTypeId(courseEntity.get(0).getCourseType());
                    studentSelectedCourse.add(chooseCourseModel);
                }
            }
        }

        return studentSelectedCourse;
    }


    //region 调用校历,计算是否在选课时间内 井朝 2018年11月23日10:46:06

    /**
     * 判断当前时间是否在选课期限内
     * 修改返回正确判断结果
     *
     * @return true:不在选课阶段 false:在选课阶段
     * @throws ParseException 类型转换异常
     */
    private boolean idDeadLine() throws ParseException {
        boolean isDeadLine = false;
        //获取当前系统时间
        String currentDate = df.format(new Date());
        Date dateNow = df.parse(currentDate);
        //获取选课的学年学期
        String semesterCode = YearSemester.getYearSemesterCode(1, 1).get(0);
        //调校历查开始和结束日期
        SchoolCalendarEntity schoolCalendarEntity = chooseCourseDao.findSCByTermIdAndEventId(semesterCode);

        if (schoolCalendarEntity != null) {
            Date startDate = schoolCalendarEntity.getStartTime();
            Date endDate = schoolCalendarEntity.getEndTime();

            //现在日期不在开始日期和结束日期之间，则return
            if (dateNow.getTime() < startDate.getTime() || dateNow.getTime() > endDate.getTime()) {
                isDeadLine = true;
            }
        }

        return isDeadLine;
    }

    /**
     * 选课 井朝 2018年11月23日10:43:02
     * 1.是否在选课时间内
     * 2.将该门课程剩余容量减1,大于等于0进行如下判断,否则直接退出
     *
     * @param addCourseInfo 课程表实体
     * @return 选课是否成功
     * @throws IOException    异常信息
     * @throws ParseException 类型转换错误
     */
    @Override
    @CacheEvict(value = {"failCourseIds"},allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public List<String> addCourse(AddCourseInfo addCourseInfo) throws IOException, ParseException {
        List<String> failCourseIds = new ArrayList<>();
        //判断是否在选课时间内
        if (idDeadLine()) {
            return failCourseIds;
        }
        //可以在这判断一下已选课并且去除已选课
        //1.如果是公选课，在课程表中把上限-1并且insert学生与上课班表--人数必须0<可选人数<上限人数
        List<AddCourseModel> addCourseModelList = addCourseInfo.getAddCourseModelList();
        String studentId = addCourseInfo.getStudentId();
        List<AddCourseModel> pubCourseLists = addCourseModelList.stream().filter(courseInfo -> courseInfo.getCourseTypeId().equals("4")).collect(Collectors.toList());
//        //java8选出所有的上课班id
//        List<String> getPubTeachClassIds = addCourseModelList.stream().map($ -> $.getTeachClassId()).collect(Collectors.toList());
        if (pubCourseLists != null && pubCourseLists.size() > 0) {
            for (AddCourseModel addCourseModel : pubCourseLists) {
                Integer courseCapacity = chooseCourseDao.minusPubCourseCapacity(addCourseModel);
                if (courseCapacity != 0) {
                    boolean addCourseFlag = studentTeachClassService.createBystudentid(studentId, addCourseModel.getTeachClassId());
                    if (addCourseFlag == false) {
                        failCourseIds.add(addCourseModel.getCourseId());
                    }
                }
            }
        }
        //2.如果是专选课，在课程表中把下限-1并且insert学生与上课班表--人数可以<0
        List<AddCourseModel> majCourseLists = addCourseModelList.stream().filter(courseInfo -> courseInfo.getCourseTypeId().equals("3")).collect(Collectors.toList());
        //java8选出所有的上课班id
//        List<String> getMajTeachClassIds = addCourseModelList.stream().map($ -> $.getTeachClassId()).collect(Collectors.toList());
        if (majCourseLists != null && majCourseLists.size() > 0) {
            for (AddCourseModel addCourseModel : majCourseLists) {
                Integer courseCapacity = chooseCourseDao.minusMajCourseCapacity(addCourseModel);
                if (courseCapacity != 0) {
                    boolean addCourseFlag = studentTeachClassService.createBystudentid(studentId, addCourseModel.getTeachClassId());
                    if (addCourseFlag == false) {
                        failCourseIds.add(addCourseModel.getCourseId());
                    }
                }
            }
        }
        return failCourseIds;
    }

    /**
     * 退课 井朝 2018年11月23日10:43:02
     *
     * @param model 课程表实体
     * @return 退课是否成功
     * @throws IOException    异常信息
     * @throws ParseException 类型转换错误
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {"deleteCourse"},allEntries = true)
    public boolean deleteCourse(AddCourseModel model) throws IOException, ParseException {
        boolean flag = false;
        //1.判断当前时间是否在选课时间内
        if (idDeadLine()) {
            return false;
        }
        String teachClassId = model.getTeachClassId();
        String studentId = model.getStudentId();
        String courseType = model.getCourseTypeId();
        //1.如果是专选课，在课程表中把上限+1并且update学生与上课班表
        if ("3".equals(courseType)) {

            Integer courseCapacity = chooseCourseDao.pulsMajCourseCapacity(model);
            flag = studentTeachClassService.deleteStudentTeachClassbyId(studentId, teachClassId);
        } else {
            //2.如果是公选课，在课程表中把下限+1并且update学生与上课班表
            Integer courseCapacity = chooseCourseDao.plusPubCourseCapacity(model);
            flag = studentTeachClassService.deleteStudentTeachClassbyId(studentId, teachClassId);
        }
        return flag;
    }

}